#include "raylib.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include <libappindicator3/app-indicator.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>

// 托盘相关全局变量
static AppIndicator* tray_indicator = NULL;
static bool is_window_hidden = false;
static SDL_Window* sdl_window = NULL;

// 下载进度全局变量
static int download_progress = -1;  // -1:无下载 0-100:进度 101:完成
static char download_status[64] = "";

typedef struct {
    char file_path[1024];
    char url[1024];
    char geometry[32];
    bool keep_cache;
} Config;

typedef struct {
    Rectangle rect;
    const char* label;
    bool is_hovered;
    bool is_pressed;
    bool is_disabled;
} Button;

typedef struct {
    Rectangle rect;
    char* text;
    int max_len;
    bool has_focus;
    const char* label;
    int start_select;
    int end_select;
    bool is_selected;
    float scroll_offset;
    char* history[30];
    int history_idx;
    int history_count;
} InputBox;

typedef struct {
    char msg[256];
    float show_time;
    float duration;
} ErrorMsg;

static Config cfg;
static Button btn_browse, btn_play, btn_stop, btn_clean, btn_help;
static InputBox input_file, input_url, input_geometry;
static bool show_help = false;
static Font font;
static const char* help_text = 
    "Usage:\n"
    "  - Select local file or enter URL (choose one)\n"
    "  - Window geometry: widthxheight+X+Y (default 1920x1080+0+0)\n"
    "  - Keep cache: Reuse cache for same URL\n"
    "  - Clean cache: Delete all cached files\n"
    "  - Press ESC to close help\n"
    "  - Ctrl+C/V/X/A/Z: Copy/Paste/Cut/SelectAll/Undo\n"
    "  - Close window to minimize to system tray";

static pid_t play_pid = -1;
static pid_t play_pgid = -1;
static ErrorMsg error_msg = {0};
static int progress_pipe[2] = {-1, -1};  // 下载进度通信管道

// 托盘菜单回调：显示窗口
static void on_menu_show(GtkWidget* widget, gpointer data) {
    is_window_hidden = false;
    SDL_ShowWindow(sdl_window);
    SetWindowFocused(true);
}

// 托盘菜单回调：退出程序
static void on_menu_quit(GtkWidget* widget, gpointer data) {
    gtk_main_quit();
    WindowShouldClose();
}

// 创建系统托盘
static void create_system_tray() {
    gtk_init(NULL, NULL);

    // 创建托盘指示器（使用系统默认媒体图标）
    tray_indicator = app_indicator_new(
        "video-desktop-player",
        "gtk-media-play",
        APP_INDICATOR_CATEGORY_APPLICATION_STATUS
    );
    app_indicator_set_status(tray_indicator, APP_INDICATOR_STATUS_ACTIVE);

    // 创建托盘菜单
    GtkWidget* menu = gtk_menu_new();
    GtkWidget* show_item = gtk_menu_item_new_with_label("Show Window");
    GtkWidget* quit_item = gtk_menu_item_new_with_label("Quit");

    // 绑定菜单回调
    g_signal_connect(show_item, "activate", G_CALLBACK(on_menu_show), NULL);
    g_signal_connect(quit_item, "activate", G_CALLBACK(on_menu_quit), NULL);

    gtk_menu_shell_append(GTK_MENU_SHELL(menu), show_item);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), quit_item);
    gtk_widget_show_all(menu);

    app_indicator_set_menu(tray_indicator, GTK_MENU(menu));

    // 托盘图标点击回调（显示/隐藏窗口）
    g_signal_connect(tray_indicator, "activate", G_CALLBACK(on_menu_show), NULL);
}

// 设置管道为非阻塞模式
static void set_pipe_nonblock(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

bool load_system_font() {
    const char* font_paths[] = {
        "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
        "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf"
    };

    for (size_t i = 0; i < sizeof(font_paths)/sizeof(font_paths[0]); i++) {
        font = LoadFontEx(font_paths[i], 16, 0, 256);
        if (font.baseSize > 0) return true;
    }

    font = GetFontDefault();
    return (font.baseSize > 0);
}

void input_history_save(InputBox* box) {
    if (box->history_count >= 30) {
        free(box->history[0]);
        for (int i = 0; i < 29; i++) box->history[i] = box->history[i+1];
        box->history_count--;
        box->history_idx--;
    }
    box->history[box->history_count] = strdup(box->text);
    box->history_count++;
    box->history_idx = box->history_count;
}

void input_history_undo(InputBox* box) {
    if (box->history_idx <= 0) return;
    box->history_idx--;
    strncpy(box->text, box->history[box->history_idx], box->max_len);
    box->text[box->max_len] = '\0';
    box->end_select = strlen(box->text);
    box->start_select = box->end_select;
    box->is_selected = false;
}

void init_input_box(InputBox* box, char* text_buf, int max_len, const char* label, Rectangle rect) {
    box->rect = rect;
    box->text = text_buf;
    box->max_len = max_len;
    box->has_focus = false;
    box->label = label;
    box->start_select = 0;
    box->end_select = 0;
    box->is_selected = false;
    box->scroll_offset = 0.0f;
    memset(box->history, 0, sizeof(box->history));
    box->history_idx = 0;
    box->history_count = 0;
    input_history_save(box);
}

void init_gui() {
    memset(cfg.file_path, 0, 1024);
    memset(cfg.url, 0, 1024);
    strcpy(cfg.geometry, "1920x1080+0+0");
    cfg.keep_cache = false;

    init_input_box(&input_file, cfg.file_path, 1023, "Local File:", (Rectangle){50, 80, 400, 30});
    init_input_box(&input_url, cfg.url, 1023, "URL:", (Rectangle){50, 140, 400, 30});
    init_input_box(&input_geometry, cfg.geometry, 31, "Window Geometry:", (Rectangle){50, 200, 200, 30});

    btn_browse = (Button){(Rectangle){470, 80, 80, 30}, "Browse...", false, false, false};
    btn_play = (Button){(Rectangle){50, 320, 120, 40}, "Play", false, false, false};
    btn_stop = (Button){(Rectangle){180, 320, 120, 40}, "Stop", false, false, true};
    btn_clean = (Button){(Rectangle){310, 320, 120, 40}, "Clean Cache", false, false, false};
    btn_help = (Button){(Rectangle){440, 320, 120, 40}, "Help", false, false, false};
}

void set_error(const char* msg, float duration) {
    strncpy(error_msg.msg, msg, sizeof(error_msg.msg)-1);
    error_msg.msg[sizeof(error_msg.msg)-1] = '\0';
    error_msg.show_time = GetTime();
    error_msg.duration = duration;
}

void delete_selected_text(InputBox* box) {
    if (!box->is_selected || box->start_select == box->end_select) return;

    input_history_save(box);
    int start = (box->start_select < box->end_select) ? box->start_select : box->end_select;
    int end = (box->start_select > box->end_select) ? box->start_select : box->end_select;
    int len = strlen(box->text);

    memmove(box->text + start, box->text + end, len - end + 1);
    box->is_selected = false;
    box->start_select = start;
    box->end_select = start;
}

void draw_input_box(InputBox* box) {
    DrawRectangleRec(box->rect, WHITE);
    DrawRectangleLinesEx(box->rect, 2, box->has_focus ? RED : BLACK);
    DrawTextEx(font, box->label, (Vector2){box->rect.x, box->rect.y - 20}, 16, 1, BLACK);

    float x_offset = box->rect.x + 5;
    float text_total_width = MeasureTextEx(font, box->text, 16, 1).x;
    float box_content_width = box->rect.width - 10;

    if (box->has_focus) {
        char cursor_prefix[1024];
        strncpy(cursor_prefix, box->text, box->end_select);
        cursor_prefix[box->end_select] = '\0';
        float cursor_x = MeasureTextEx(font, cursor_prefix, 16, 1).x - box->scroll_offset;

        if (cursor_x < 0) box->scroll_offset = MeasureTextEx(font, cursor_prefix, 16, 1).x;
        else if (cursor_x > box_content_width) box->scroll_offset = MeasureTextEx(font, cursor_prefix, 16, 1).x - box_content_width;
    }

    if (text_total_width > box_content_width) {
        DrawTextEx(font, box->text, (Vector2){x_offset - box->scroll_offset, box->rect.y + 5}, 16, 1, BLACK);
    } else {
        DrawTextEx(font, box->text, (Vector2){x_offset, box->rect.y + 5}, 16, 1, BLACK);
    }

    if (box->is_selected && box->start_select != box->end_select) {
        int start = (box->start_select < box->end_select) ? box->start_select : box->end_select;
        int end = (box->start_select > box->end_select) ? box->start_select : box->end_select;

        char temp[1024];
        strncpy(temp, box->text, start);
        temp[start] = '\0';
        float start_x = x_offset + MeasureTextEx(font, temp, 16, 1).x - box->scroll_offset;

        strncpy(temp, box->text + start, end - start);
        temp[end - start] = '\0';
        float select_width = MeasureTextEx(font, temp, 16, 1).x;

        if (start_x + select_width > x_offset && start_x < x_offset + box_content_width) {
            float draw_start = (start_x < x_offset) ? x_offset : start_x;
            float draw_width = select_width - (draw_start - start_x);
            if (draw_start + draw_width > x_offset + box_content_width) draw_width = x_offset + box_content_width - draw_start;
            DrawRectangleRec((Rectangle){draw_start, box->rect.y + 5, draw_width, 20}, (Color){200, 220, 255, 255});
        }
    }

    if (box->has_focus) {
        char cursor_prefix[1024];
        strncpy(cursor_prefix, box->text, box->end_select);
        cursor_prefix[box->end_select] = '\0';
        float cursor_x = x_offset + MeasureTextEx(font, cursor_prefix, 16, 1).x - box->scroll_offset;
        DrawLine(cursor_x, box->rect.y + 5, cursor_x, box->rect.y + 25, BLACK);
    }
}

void draw_button(Button* btn) {
    Color bg = WHITE;
    Color text_color = BLACK;

    if (btn->is_disabled) {
        bg = LIGHTGRAY;
        text_color = GRAY;
    } else {
        if (btn->is_pressed) bg = GRAY;
        else if (btn->is_hovered) bg = LIGHTGRAY;
    }

    DrawRectangleRec(btn->rect, bg);
    DrawRectangleLinesEx(btn->rect, 2, btn->is_disabled ? GRAY : BLACK);

    Vector2 text_size = MeasureTextEx(font, btn->label, 16, 1);
    DrawTextEx(
        font,
        btn->label,
        (Vector2){
            btn->rect.x + (btn->rect.width - text_size.x)/2,
            btn->rect.y + (btn->rect.height - text_size.y)/2
        },
        16, 1, text_color
    );
}

void draw_error() {
    if (GetTime() - error_msg.show_time > error_msg.duration) return;
    float msg_width = MeasureTextEx(font, error_msg.msg, 16, 1).x;
    Rectangle error_rect = {(600 - msg_width - 20)/2, 370, msg_width + 20, 25};
    DrawRectangleRec(error_rect, (Color){255, 220, 220, 255});
    DrawRectangleLinesEx(error_rect, 1, RED);
    DrawTextEx(font, error_msg.msg, (Vector2){error_rect.x + 10, error_rect.y + 3}, 16, 1, RED);
}

// 绘制下载进度条
void draw_download_progress() {
    if (download_progress < 0) return;

    // 进度条背景
    Rectangle progress_bg = {50, 355, 500, 10};
    DrawRectangleRec(progress_bg, LIGHTGRAY);

    // 进度条前景
    float progress_width = (download_progress > 100 ? 100 : download_progress) * 5.0f;
    Rectangle progress_fg = {50, 355, progress_width, 10};
    DrawRectangleRec(progress_fg, (Color){0, 180, 0, 255});

    // 进度文字
    char progress_text[32];
    if (download_progress == 101) {
        strcpy(progress_text, "Download completed!");
    } else {
        snprintf(progress_text, sizeof(progress_text), "Download: %d%%", download_progress);
    }
    float text_width = MeasureTextEx(font, progress_text, 12, 1).x;
    DrawTextEx(font, progress_text, (Vector2){(600 - text_width)/2, 340}, 12, 1, DARKGRAY);

    // 进度完成后3秒重置
    if (download_progress == 101 && GetTime() - error_msg.show_time > 3.0f) {
        download_progress = -1;
        download_status[0] = '\0';
    }
}

void copy_text(InputBox* box) {
    if (!box->has_focus) return;

    char temp[1024];
    if (box->is_selected && box->start_select != box->end_select) {
        int start = (box->start_select < box->end_select) ? box->start_select : box->end_select;
        int end = (box->start_select > box->end_select) ? box->start_select : box->end_select;
        strncpy(temp, box->text + start, end - start);
        temp[end - start] = '\0';
    } else {
        strncpy(temp, box->text, sizeof(temp)-1);
        temp[sizeof(temp)-1] = '\0';
    }

    FILE* pipe = popen("xclip -selection clipboard", "w");
    if (pipe) {
        fwrite(temp, 1, strlen(temp), pipe);
        pclose(pipe);
    }
}

void cut_text(InputBox* box) {
    if (!box->has_focus) return;
    input_history_save(box);
    copy_text(box);
    delete_selected_text(box);
}

void paste_text(InputBox* box) {
    if (!box->has_focus) return;

    FILE* pipe = popen("xclip -selection clipboard -o", "r");
    if (!pipe) return;

    char buf[1024];
    size_t read_len = fread(buf, 1, sizeof(buf)-1, pipe);
    pclose(pipe);
    if (read_len == 0) return;

    buf[read_len] = '\0';
    size_t current_len = strlen(box->text);

    if (current_len + read_len >= box->max_len) {
        set_error("Text too long to paste", 3.0f);
        return;
    }

    input_history_save(box);
    if (box->is_selected) delete_selected_text(box);
    current_len = strlen(box->text);

    memmove(box->text + current_len, buf, read_len + 1);
    box->end_select = current_len + read_len;
    box->start_select = box->end_select;
}

void select_all_text(InputBox* box) {
    if (!box->has_focus) return;
    box->start_select = 0;
    box->end_select = strlen(box->text);
    box->is_selected = true;
}

void handle_input(InputBox* box) {
    if (!box->has_focus) return;

    if (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) {
        if (IsKeyPressed(KEY_C)) { copy_text(box); return; }
        if (IsKeyPressed(KEY_V)) { paste_text(box); return; }
        if (IsKeyPressed(KEY_X)) { cut_text(box); return; }
        if (IsKeyPressed(KEY_A)) { select_all_text(box); return; }
        if (IsKeyPressed(KEY_Z)) { input_history_undo(box); return; }
    }

    int key = GetKeyPressed();
    while (key > 0) {
        input_history_save(box);
        if (key == KEY_BACKSPACE) {
            if (box->is_selected) {
                delete_selected_text(box);
            } else if (strlen(box->text) > 0) {
                box->text[strlen(box->text)-1] = '\0';
                box->end_select--;
                box->start_select = box->end_select;
            }
        }
        else if (key == KEY_EQUAL && (IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT))) {
            if (box->is_selected) delete_selected_text(box);
            size_t current_len = strlen(box->text);
            if (current_len < box->max_len) {
                box->text[current_len] = '+';
                box->text[current_len+1] = '\0';
                box->end_select++;
                box->start_select = box->end_select;
            }
        }
        else if (key >= 32 && key <= 126 && strlen(box->text) < box->max_len) {
            if (box->is_selected) delete_selected_text(box);
            size_t current_len = strlen(box->text);
            memmove(box->text + current_len + 1, box->text + current_len, 1);
            box->text[current_len] = (char)key;
            box->end_select++;
            box->start_select = box->end_select;
        }
        key = GetKeyPressed();
    }
}

void open_file_dialog() {
    FILE* pipe = popen("zenity --file-selection --title='Select Video File'", "r");
    if (!pipe) {
        set_error("File dialog failed", 3.0f);
        return;
    }

    char path[1024];
    if (fgets(path, sizeof(path), pipe)) {
        path[strcspn(path, "\n")] = '\0';
        input_history_save(&input_file);
        strcpy(cfg.file_path, path);
    } else {
        set_error("No file selected", 2.0f);
    }
    pclose(pipe);
}

void stop_cli() {
    if (play_pgid > 0) {
        killpg(play_pgid, SIGTERM);
        waitpid(-play_pgid, NULL, WNOHANG);
        play_pid = -1;
        play_pgid = -1;
        btn_stop.is_disabled = true;
        btn_play.is_disabled = false;
        set_error("Playback stopped", 2.0f);
        download_progress = -1;  // 停止时重置下载进度
    } else {
        set_error("No active playback", 2.0f);
    }

    // 关闭管道
    if (progress_pipe[0] != -1) {
        close(progress_pipe[0]);
        progress_pipe[0] = -1;
    }
    if (progress_pipe[1] != -1) {
        close(progress_pipe[1]);
        progress_pipe[1] = -1;
    }
}

pid_t exec_process(const char* cmd) {
    pid_t pid = fork();
    if (pid == 0) {
        execl("/bin/sh", "sh", "-c", cmd, NULL);
        exit(1);
    }
    return pid;
}

// 解析下载进度（从管道读取数据）
void parse_download_progress() {
    if (progress_pipe[0] == -1) return;

    char buf[64];
    ssize_t len = read(progress_pipe[0], buf, sizeof(buf)-1);
    if (len <= 0) return;

    buf[len] = '\0';
    char* progress_str = strstr(buf, "PROGRESS:");
    if (progress_str) {
        progress_str += 9;
        int prog = atoi(progress_str);
        if (prog >= 0 && prog <= 100) {
            download_progress = prog;
            set_error("Downloading...", 1.0f);  // 保持提示不消失
        } else if (prog == 101) {
            download_progress = 101;  // 下载完成
            set_error("Download completed", 3.0f);
        }
    }
}

void run_cli() {
    if (play_pgid > 0) stop_cli();

    if ((strlen(cfg.file_path) == 0 && strlen(cfg.url) == 0) ||
        (strlen(cfg.file_path) > 0 && strlen(cfg.url) > 0)) {
        set_error("Select local file OR URL (not both)", 3.0f);
        return;
    }

    // 创建进度通信管道
    if (pipe(progress_pipe) == -1) {
        set_error("Failed to create progress pipe", 3.0f);
        return;
    }
    set_pipe_nonblock(progress_pipe[0]);

    char cmd[4096] = "./peruere ";
    size_t len = strlen(cmd);

    if (strlen(cfg.file_path) > 0) {
        snprintf(cmd + len, sizeof(cmd) - len, "--file \"%s\" ", cfg.file_path);
        len = strlen(cmd);
    }
    if (strlen(cfg.url) > 0) {
        snprintf(cmd + len, sizeof(cmd) - len, "--url \"%s\" ", cfg.url);
        len = strlen(cmd);
    }
    snprintf(cmd + len, sizeof(cmd) - len, "--geometry %s ", cfg.geometry);
    len = strlen(cmd);
    if (cfg.keep_cache) {
        strncat(cmd, "--keep", sizeof(cmd) - len - 1);
    }

    // 子进程stdout重定向到管道（用于输出进度）
    play_pid = fork();
    if (play_pid == 0) {
        close(progress_pipe[0]);
        dup2(progress_pipe[1], STDOUT_FILENO);  // stdout -> 管道
        dup2(progress_pipe[1], STDERR_FILENO);  // stderr也重定向（避免遗漏）
        setpgid(0, 0);
        execl("/bin/sh", "sh", "-c", cmd, NULL);
        exit(1);
    } else if (play_pid > 0) {
        close(progress_pipe[1]);
        play_pgid = play_pid;
        btn_play.is_disabled = true;
        btn_stop.is_disabled = false;
        download_progress = 0;  // 初始化进度为0
        set_error("Downloading...", 1.0f);
    } else {
        set_error("Failed to start playback", 3.0f);
        close(progress_pipe[0]);
        close(progress_pipe[1]);
        progress_pipe[0] = progress_pipe[1] = -1;
    }
}

void clean_cache() {
    if (play_pgid > 0) stop_cli();
    pid_t pid = exec_process("./peruere --clean-cache");
    if (pid > 0) {
        waitpid(pid, NULL, WNOHANG);
        set_error("Cache cleaned", 2.0f);
    } else {
        set_error("Failed to clean cache", 3.0f);
    }
}

void cleanup_play_process() {
    if (play_pgid > 0) {
        killpg(play_pgid, SIGTERM);
        waitpid(-play_pgid, NULL, 0);
    }
    for (int i = 0; i < input_file.history_count; i++) free(input_file.history[i]);
    for (int i = 0; i < input_url.history_count; i++) free(input_url.history[i]);
    for (int i = 0; i < input_geometry.history_count; i++) free(input_geometry.history[i]);

    // 清理管道和托盘
    if (progress_pipe[0] != -1) close(progress_pipe[0]);
    if (progress_pipe[1] != -1) close(progress_pipe[1]);
    if (tray_indicator) g_object_unref(tray_indicator);
}

// GTK主循环回调（用于Raylib绘制）
static gboolean gtk_raylib_loop(gpointer data) {
    if (is_window_hidden) return G_SOURCE_CONTINUE;

    // 处理Raylib事件
    SDL_Event ev;
    while (SDL_PollEvent(&ev)) {
        if (ev.type == SDL_QUIT) {
            // 窗口关闭事件：隐藏到托盘
            is_window_hidden = true;
            SDL_HideWindow(sdl_window);
            return G_SOURCE_CONTINUE;
        }
        RaylibProcessEvent(&ev);
    }

    // 解析下载进度
    parse_download_progress();

    // Raylib绘制逻辑
    Vector2 mouse = GetMousePosition();

    if (IsKeyPressed(KEY_ESCAPE)) {
        if (show_help) show_help = false;
        else {
            is_window_hidden = true;
            SDL_HideWindow(sdl_window);
        }
    }

    btn_browse.is_hovered = !btn_browse.is_disabled && CheckCollisionPointRec(mouse, btn_browse.rect);
    btn_play.is_hovered = !btn_play.is_disabled && CheckCollisionPointRec(mouse, btn_play.rect);
    btn_stop.is_hovered = !btn_stop.is_disabled && CheckCollisionPointRec(mouse, btn_stop.rect);
    btn_clean.is_hovered = !btn_clean.is_disabled && CheckCollisionPointRec(mouse, btn_clean.rect);
    btn_help.is_hovered = !btn_help.is_disabled && CheckCollisionPointRec(mouse, btn_help.rect);

    if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) {
        bool prev_focus_file = input_file.has_focus;
        bool prev_focus_url = input_url.has_focus;
        bool prev_focus_geo = input_geometry.has_focus;

        input_file.has_focus = CheckCollisionPointRec(mouse, input_file.rect);
        input_url.has_focus = CheckCollisionPointRec(mouse, input_url.rect);
        input_geometry.has_focus = CheckCollisionPointRec(mouse, input_geometry.rect);

        if (!prev_focus_file && input_file.has_focus) {
            input_url.is_selected = false;
            input_geometry.is_selected = false;
            char temp[1024];
            strncpy(temp, input_file.text, sizeof(temp)-1);
            float click_x = mouse.x - input_file.rect.x - 5 + input_file.scroll_offset;
            int len = strlen(temp);
            input_file.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_file.end_select = i;
            }
            input_file.start_select = input_file.end_select;
        }
        if (!prev_focus_url && input_url.has_focus) {
            input_file.is_selected = false;
            input_geometry.is_selected = false;
            char temp[1024];
            strncpy(temp, input_url.text, sizeof(temp)-1);
            float click_x = mouse.x - input_url.rect.x - 5 + input_url.scroll_offset;
            int len = strlen(temp);
            input_url.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_url.end_select = i;
            }
            input_url.start_select = input_url.end_select;
        }
        if (!prev_focus_geo && input_geometry.has_focus) {
            input_file.is_selected = false;
            input_url.is_selected = false;
            char temp[1024];
            strncpy(temp, input_geometry.text, sizeof(temp)-1);
            float click_x = mouse.x - input_geometry.rect.x - 5 + input_geometry.scroll_offset;
            int len = strlen(temp);
            input_geometry.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_geometry.end_select = i;
            }
            input_geometry.start_select = input_geometry.end_select;
        }

        if (btn_browse.is_hovered) open_file_dialog();
        if (btn_play.is_hovered) run_cli();
        if (btn_stop.is_hovered) stop_cli();
        if (btn_clean.is_hovered) clean_cache();
        if (btn_help.is_hovered) show_help = !show_help;

        if (CheckCollisionPointRec(mouse, (Rectangle){50, 260, 20, 20})) {
            cfg.keep_cache = !cfg.keep_cache;
        }
    }

    if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
        if (input_file.has_focus) {
            char temp[1024];
            strncpy(temp, input_file.text, sizeof(temp)-1);
            float click_x = mouse.x - input_file.rect.x - 5 + input_file.scroll_offset;
            int len = strlen(temp);
            input_file.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_file.end_select = i;
            }
            input_file.is_selected = true;
        }
        if (input_url.has_focus) {
            char temp[1024];
            strncpy(temp, input_url.text, sizeof(temp)-1);
            float click_x = mouse.x - input_url.rect.x - 5 + input_url.scroll_offset;
            int len = strlen(temp);
            input_url.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_url.end_select = i;
            }
            input_url.is_selected = true;
        }
        if (input_geometry.has_focus) {
            char temp[1024];
            strncpy(temp, input_geometry.text, sizeof(temp)-1);
            float click_x = mouse.x - input_geometry.rect.x - 5 + input_geometry.scroll_offset;
            int len = strlen(temp);
            input_geometry.end_select = 0;
            for (int i = 0; i <= len; i++) {
                temp[i] = '\0';
                float width = MeasureTextEx(font, temp, 16, 1).x;
                if (width > click_x) break;
                input_geometry.end_select = i;
            }
            input_geometry.is_selected = true;
        }
    }

    btn_browse.is_pressed = btn_browse.is_hovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT);
    btn_play.is_pressed = btn_play.is_hovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT);
    btn_stop.is_pressed = btn_stop.is_hovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT);
    btn_clean.is_pressed = btn_clean.is_hovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT);
    btn_help.is_pressed = btn_help.is_hovered && IsMouseButtonDown(MOUSE_BUTTON_LEFT);

    handle_input(&input_file);
    handle_input(&input_url);
    handle_input(&input_geometry);

    BeginDrawing();
    ClearBackground(RAYWHITE);

    DrawTextEx(font, "Video Desktop Player", (Vector2){200, 20}, 24, 1, DARKGRAY);

    draw_input_box(&input_file);
    draw_input_box(&input_url);
    draw_input_box(&input_geometry);

    draw_button(&btn_browse);
    draw_button(&btn_play);
    draw_button(&btn_stop);
    draw_button(&btn_clean);
    draw_button(&btn_help);

    DrawRectangleLines(50, 260, 20, 20, BLACK);
    if (cfg.keep_cache) DrawRectangle(52, 262, 16, 16, BLACK);
    DrawTextEx(font, "Keep Cache (-k)", (Vector2){80, 260}, 16, 1, BLACK);

    if (show_help) {
        DrawRectangle(50, 50, 500, 300, WHITE);
        DrawRectangleLines(50, 50, 500, 300, RED);
        
        char buf[1024];
        strncpy(buf, help_text, sizeof(buf)-1);
        char* line = strtok(buf, "\n");
        float y = 70;
        while (line) {
            DrawTextEx(font, line, (Vector2){70, y}, 16, 1, BLACK);
            y += 20;
            line = strtok(NULL, "\n");
        }
    }

    draw_error();
    draw_download_progress();  // 绘制下载进度

    EndDrawing();

    return G_SOURCE_CONTINUE;
}

int main() {
    atexit(cleanup_play_process);

    // 初始化Raylib（获取SDL窗口指针）
    InitWindow(600, 400, "Video Desktop Player");
    sdl_window = GetWindowHandle();  // Raylib获取SDL窗口
    SetTargetFPS(60);

    // 创建系统托盘
    create_system_tray();

    if (!load_system_font()) {
        fprintf(stderr, "Font load failed\n");
        CloseWindow();
        return 1;
    }

    init_gui();

    // 添加Raylib循环到GTK主循环（16ms间隔，约60FPS）
    g_timeout_add(16, gtk_raylib_loop, NULL);

    // 启动GTK主循环（托盘依赖GTK）
    gtk_main();

    // 退出时清理
    UnloadFont(font);
    CloseWindow();
    return 0;
}
